package routers

import (
	"database/sql"
	"net/http"
	"punch/dbs"
	"punch/utils"
	"strconv"

	"github.com/gin-gonic/gin"
)

func LoadStudent(e *gin.Engine) {
	e.POST("/punc/student/add", studentAddHandler)
	e.POST("/punc/student/delete", studentDeleteHandler)
	e.POST("/punc/student/edit", studentEditHandler)
	e.POST("/punc/student/get", studentGetHandler)
}

// 定义数据表结构体
type Student struct {
	Id          int            `db:"id"`
	Org_id      int            `db:"org_id"`
	Org_name    sql.NullString `db:"org_name"`
	Name        string         `db:"name"`
	Sex         string         `db:"sex"`
	Phone       string         `db:"phone"`
	Email       string         `db:"email"`
	Class       string         `db:"class"`
	Apartment   string         `db:"apartment"`
	Avatar      string         `db:"avatar"`
	Note        string         `db:"note"`
	Credit      int            `db:"credit"`
	Points      int            `db:"points"`
	Peract_repu string         `db:"peract_repu"`
	Triact_repu string         `db:"triact_repu"`
	Sno         string         `db:"sno"`
	Password    string         `db:"password"`
	Type        int            `db:"type"`
	Create_time string         `db:"create_time"`
	Update_time string         `db:"update_time"`
}

// 定义添加数据结构体
type StudentParamsAdd struct {
	Org_id    int    `json:"org_id" binding:"required"`
	Name      string `json:"name" binding:"required"`
	Sex       string `json:"sex" binding:"required"`
	Phone     string `json:"phone" binding:"required"`
	Email     string `json:"email" binding:"required"`
	Class     string `json:"class" binding:"required"`
	Apartment string `json:"apartment" binding:"required"`
	Avatar    string `json:"avatar" binding:"required"`
	Note      string `json:"note" binding:"required"`
	Sno       string `json:"sno" binding:"required"`
	Type      int    `json:"type" binding:"required"`
}

// 定义删除数据结构体
type StudentParamsDelete struct {
	Id int `json:"id" bingding:"required"`
}

// 定义更新数据结构体
type StudentParamsEdit struct {
	Id        int    `json:"id" binding:"required"`
	Org_id    int    `json:"org_id" binding:"required"`
	Name      string `json:"name" binding:"required"`
	Sex       string `json:"sex" binding:"required"`
	Phone     string `json:"phone" binding:"required"`
	Email     string `json:"email" binding:"required"`
	Class     string `json:"class" binding:"required"`
	Apartment string `json:"apartment" binding:"required"`
	Avatar    string `json:"avatar" binding:"required"`
	Note      string `json:"note" binding:"required"`
	Sno       string `json:"sno" binding:"required"`
	Type      int    `json:"type" binding:"required"`
	Password  string `json:"password"`
}

// 定义查询数据结构体
type StudentParamsGet struct {
	PageNo    int    `json:"pageNo"`
	PageSize  int    `json:"pageSize"`
	Id        int    `json:"id"`
	Org_id    int    `json:"org_id"`
	Name      string `json:"name"`
	Sex       string `json:"sex"`
	Phone     string `json:"phone"`
	Email     string `json:"email"`
	Class     string `json:"class"`
	Apartment string `json:"apartment"`
	Sno       string `json:"sno"`
	Type      int    `json:"type"`
}

func studentAddHandler(c *gin.Context) {
	if tempUserType, _ := c.Get("Usertype"); tempUserType != "manager" && tempUserType != "teacher" {
		c.JSON(http.StatusOK, gin.H{
			"code": 20020,
			"msg":  "权限不足",
		})
		return
	}

	var params StudentParamsAdd
	if err := c.ShouldBindJSON(&params); err != nil {
		c.JSON(http.StatusOK, gin.H{
			"code": 20003,
			"msg":  err.Error(),
		})
		return
	}

	db, err := dbs.Conn(c)
	if err != nil {
		db.Close()
		return
	}

	if tempUserType, _ := c.Get("Usertype"); tempUserType == "teacher" {
		tempOrgID, _ := c.Get("UserOrgID")
		params.Org_id = tempOrgID.(int)
	}

	r, err := db.Exec("insert into student(org_id, name, sex, phone, email, class, apartment, avatar, note, sno, type, password)"+
		"values(?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)",
		params.Org_id, params.Name, params.Sex, params.Phone, params.Email, params.Class, params.Apartment, params.Avatar,
		params.Note, params.Sno, params.Type, utils.GetMD5(utils.DEFAULT_PASSWORD))
	if err != nil {
		c.JSON(http.StatusOK, gin.H{
			"code": 20004,
			"msg":  err.Error(),
		})
		return
	}
	id, err := r.LastInsertId()
	if err != nil {
		c.JSON(http.StatusOK, gin.H{
			"code": 20000,
			"msg":  err.Error(),
		})
		return
	}

	var student []Student
	tempSql := "select s.id, s.org_id, org.name as org_name, s.name, s.sex, s.phone, s.email, s.class, s.apartment," +
		" s.avatar, s.note, s.credit, s.points, s.peract_repu, s.triact_repu, s.sno, s.type, s.create_time, s.update_time" +
		" from student as s left join org on s.org_id=org.id where s.id=?"
	err = db.Select(&student, tempSql, id)
	if err != nil {
		c.JSON(http.StatusOK, gin.H{
			"code": 20056,
			"msg":  err.Error(),
		})
		return
	}
	if len(student) == 0 {
		c.JSON(http.StatusOK, gin.H{
			"code": 20000,
			"msg":  "添加成功，请刷新查看",
			"data": gin.H{
				"Id": id,
			},
		})
		return
	}

	c.JSON(http.StatusOK, gin.H{
		"code": 20000,
		"msg":  "添加成功",
		"data": student[0],
	})

	db.Close()
}

func studentDeleteHandler(c *gin.Context) {
	if tempUserType, _ := c.Get("Usertype"); tempUserType != "manager" && tempUserType != "teacher" {
		c.JSON(http.StatusOK, gin.H{
			"code": 20020,
			"msg":  "权限不足",
		})
		return
	}

	var params StudentParamsDelete
	if err := c.ShouldBindJSON(&params); err != nil {
		c.JSON(http.StatusOK, gin.H{
			"code": 20003,
			"msg":  err.Error(),
		})
		return
	}

	db, err := dbs.Conn(c)
	if err != nil {
		db.Close()
		return
	}

	_, err = db.Exec("delete from student where id=?", params.Id)
	if err != nil {
		c.JSON(http.StatusOK, gin.H{
			"code": 20004,
			"msg":  err.Error(),
		})
		return
	}
	c.JSON(http.StatusOK, gin.H{
		"code": 20000,
		"msg":  "删除成功",
		"data": gin.H{
			"Id": params.Id,
		},
	})

	db.Close()
}

func studentEditHandler(c *gin.Context) {
	if tempUserType, _ := c.Get("Usertype"); tempUserType != "manager" && tempUserType != "teacher" && tempUserType != "student" {
		c.JSON(http.StatusOK, gin.H{
			"code": 20020,
			"msg":  "权限不足",
		})
		return
	}

	var params StudentParamsEdit
	if err := c.ShouldBindJSON(&params); err != nil {
		c.JSON(http.StatusOK, gin.H{
			"code": 20003,
			"msg":  err.Error(),
		})
		return
	}

	if tempUserType, _ := c.Get("Usertype"); tempUserType == "student" {
		if tempID, _ := c.Get("UserID"); params.Id != tempID.(int) {
			c.JSON(http.StatusOK, gin.H{
				"code": 20020,
				"msg":  "权限不足",
			})
			return
		}
	}

	db, err := dbs.Conn(c)
	if err != nil {
		// 这里没有返回报错信息是因为dbs.Conn中已经定义
		db.Close()
		return
	}

	var student []Student
	err = db.Select(&student, "select * from student where id=?", params.Id)
	if err != nil {
		c.JSON(http.StatusOK, gin.H{
			"code": 20023,
			"msg":  err.Error(),
		})
		return
	}
	if len(student) == 0 {
		c.JSON(http.StatusOK, gin.H{
			"code": 20030,
			"msg":  "没有此位学生",
			"data": gin.H{
				"Id": params.Id,
			},
		})
		return
	}

	student[0].Name = params.Name
	student[0].Sex = params.Sex
	student[0].Phone = params.Phone
	student[0].Email = params.Email
	student[0].Class = params.Class
	student[0].Apartment = params.Apartment
	student[0].Avatar = params.Avatar
	student[0].Note = params.Note
	student[0].Sno = params.Sno
	student[0].Type = params.Type
	if params.Password != "" {
		student[0].Password = utils.GetMD5(params.Password)
	}

	_, err = db.Exec("update student set name=?, sex=?, phone=?, email=?, class=?, apartment=?, avatar=?, note=?, sno=?, type=?, password=? where id=?",
		student[0].Name, student[0].Sex, student[0].Phone, student[0].Email, student[0].Class,
		student[0].Apartment, student[0].Avatar, student[0].Note, student[0].Sno, student[0].Type, student[0].Password, params.Id)
	if err != nil {
		c.JSON(http.StatusOK, gin.H{
			"code": 20025,
			"msg":  err.Error(),
		})
		return
	}

	var student2 []Student
	tempSql := "select s.id, s.org_id, org.name as org_name, s.name, s.sex, s.phone, s.email, s.class, s.apartment," +
		" s.avatar, s.note, s.credit, s.points, s.peract_repu, s.triact_repu, s.sno, s.type, s.create_time, s.update_time" +
		" from student as s left join org on s.org_id=org.id where s.id=?"
	err = db.Select(&student2, tempSql, params.Id)
	if err != nil {
		c.JSON(http.StatusOK, gin.H{
			"code": 20023,
			"msg":  err.Error(),
		})
		return
	}

	if len(student2) == 0 {
		c.JSON(http.StatusOK, gin.H{
			"code": 20025,
			"msg":  "没有这位学生",
		})
		return
	}

	c.JSON(http.StatusOK, gin.H{
		"code": 20000,
		"msg":  "更新成功",
		"data": student2[0],
	})

	db.Close()
}

func studentGetHandler(c *gin.Context) {
	if tempUserType, _ := c.Get("Usertype"); tempUserType != "manager" && tempUserType != "teacher" {
		c.JSON(http.StatusOK, gin.H{
			"code": 20020,
			"msg":  "权限不足",
		})
		return
	}

	var params StudentParamsGet
	if err := c.ShouldBindJSON(&params); err != nil {
		c.JSON(http.StatusOK, gin.H{
			"code": 20003,
			"msg":  err.Error(),
		})
		return
	}

	db, err := dbs.Conn(c)
	if err != nil {
		db.Close()
		return
	}

	if tempUserType, _ := c.Get("Usertype"); tempUserType == "teacher" {
		tempOrgID, _ := c.Get("UserOrgID")
		params.Org_id = tempOrgID.(int)
	}

	tempSql := "select s.id, s.org_id, org.name as org_name, s.name, s.sex, s.phone, s.email, s.class, s.apartment," +
		" s.avatar, s.note, s.credit, s.points, s.peract_repu, s.triact_repu, s.sno, s.type, s.create_time, s.update_time" +
		" from student as s left join org on s.org_id=org.id"
	hasAnd := " where"
	if params.Id != 0 {
		tempSql = tempSql + hasAnd + " s.id=" + strconv.Itoa(params.Id)
		hasAnd = " and"
	}
	if params.Org_id != 0 {
		tempSql = tempSql + hasAnd + " s.org_id=" + strconv.Itoa(params.Org_id)
		hasAnd = " and"
	}
	if params.Name != "" {
		tempSql = tempSql + hasAnd + " s.name like '%" + params.Name + "%'"
		hasAnd = " and"
	}
	if params.Sex != "" {
		tempSql = tempSql + hasAnd + " s.sex like '%" + params.Name + "%'"
		hasAnd = " and"
	}
	if params.Phone != "" {
		tempSql = tempSql + hasAnd + " s.phone like '%" + params.Phone + "%'"
		hasAnd = " and"
	}
	if params.Email != "" {
		tempSql = tempSql + hasAnd + " s.email like '%" + params.Email + "%'"
		hasAnd = " and"
	}
	if params.Class != "" {
		tempSql = tempSql + hasAnd + " s.class like '%" + params.Class + "%'"
		hasAnd = " and"
	}
	if params.Apartment != "" {
		tempSql = tempSql + hasAnd + " s.apartment like '%" + params.Apartment + "%'"
		hasAnd = " and"
	}
	if params.Class != "" {
		tempSql = tempSql + hasAnd + " s.class like '%" + params.Class + "%'"
		hasAnd = " and"
	}
	if params.Sno != "" {
		tempSql = tempSql + hasAnd + " s.sno like '%" + params.Sno + "%'"
		hasAnd = " and"
	}
	if params.Type != 0 {
		tempSql = tempSql + hasAnd + " s.type=" + strconv.Itoa(params.Type)
		hasAnd = " and"
	}
	tempSql = tempSql + " order by s.create_time desc"
	if params.PageNo != 0 && params.PageSize != 0 {
		tempSql = tempSql + " limit " + strconv.Itoa((params.PageNo-1)*params.PageSize) + "," + strconv.Itoa(params.PageSize)
	}

	var student []Student
	err = db.Select(&student, tempSql)
	if err != nil {
		c.JSON(http.StatusOK, gin.H{
			"code": 20004,
			"msg":  err.Error(),
		})
		return
	}

	if len(student) == 0 {
		c.JSON(http.StatusOK, gin.H{
			"code": 20068,
			"msg":  "没有找到",
		})
		return
	}

	c.JSON(http.StatusOK, gin.H{
		"code": 20000,
		"msg":  "查询成功",
		"data": student,
	})

	db.Close()
}
